package com.ericsson.resourceplanner.dao.impl;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.ericsson.resourceplanner.dao.ReportDataDAO;
import com.ericsson.resourceplanner.dao.entity.EmpDetails;
import com.ericsson.resourceplanner.dao.entity.EmployeeProject;
import com.ericsson.resourceplanner.dao.entity.Report;
import com.ericsson.resourceplanner.dao.entity.WeekUtilization;
import com.ericsson.resourceplanner.dto.ReportDto;
import com.ericsson.resourceplanner.dto.ReportStructure;
import com.ericsson.resourceplanner.utils.NumberOfWorkingDays;


@Repository
public class ReportDataDaoImpl implements ReportDataDAO{

	@PersistenceContext
	EntityManager entityManager;	
	@Override
	public List<ReportDto> getUtilisationReport(String mon , String yr) {
		// TODO Auto-generated method stub
	Map<String,List<ReportStructure>> report_map = new HashMap<String,List<ReportStructure>>();	
//	Map<String,Map<String, String>> map2  = new HashMap<String,Map<String, String>>();		
    List<ReportDto> output_report = new ArrayList<ReportDto>();
    System.out.println("INPUT MONTH and YEAR:"+mon+":"+yr);
    Map<String, List<String>> week_list_map = new HashMap<String, List<String>>();
   
    String end_day ="";
    String strat_dat="";
    String end_dat = "";
    int week_of_month ;
   
    int no_of_wkDays ;
    String query = "";
	// String query = "select *  from employee e , project p , employee_project ep , week_utilization w  where e.id  = ep.employee_id  and p.id  = ep.project_id and ep.id  = w.employee_project_id";
    String icrrb_hr= "";
    String input_month ="";
     if("JAN".equals(mon)){
    	 input_month ="1"; 
    	 end_day ="31";
     }
     else if("FEB".equals(mon)){
    	 input_month="2";
    	 end_day ="28";
     }
     else if("MAR".equals(mon)){
    	 input_month="3";
    	 end_day ="31";
     }
     else if("APR".equals(mon)){
    	 input_month="4";
    	 end_day ="30";
     }
     else if("MAY".equals(mon)){
    	 input_month="5";
    	 end_day ="31";
     }
     else if("JUN".equals(mon)){
    	 input_month="6";
    	 end_day ="30";
     }
     else if("JUL".equals(mon)){
    	 input_month="7";
    	 end_day ="31";
     }
     else if("AUG".equals(mon)){
    	 input_month="8";
    	 end_day ="31";
     }
     else if("SEP".equals(mon)){
    	 input_month="9";
    	 end_day ="30";
     }
     else if("OCT".equals(mon)){
    	 input_month="10";
    	 end_day ="31";
     }
     else if("NOV".equals(mon)){
    	 input_month="11";
    	 end_day ="30";
     }
     else if("DEC".equals(mon)){
    	 input_month="12";
    	 end_day ="31";
     }
     
       System.out.println("input month and year:"+input_month+"year:"+yr);
    
      if(input_month!=null && (!"".equals(input_month)) && yr!=null && (!"".equals(yr))){
    	  strat_dat = "01"+"-"+mon+"-"+yr; 
    	  end_dat = end_day+"-"+mon+"-"+yr;
    	  no_of_wkDays  =   NumberOfWorkingDays.getNoOfWorkingDays(strat_dat, end_dat);
    	  System.out.println("no_of_wkDays:"+no_of_wkDays);
    	  System.out.println("INDAOIMPL INPUT MONTH and YR:"+input_month+":"+yr);
    	  System.out.println("strat_dat:"+strat_dat+"end_dat:"+end_dat);
    	  int months = Integer.valueOf(input_month)-1;
    
    	  week_of_month =  getWeekNumber(months,Integer.valueOf(yr)); 
    	 
      query = "select e.id as empid , e.signum_id as signum ,e.password as pwd  , e.emp_name  as Ename, e.manager_id as ManagerID , p.id as ids ,  p.pid ,  p.pname , p.region, p.customer , p.domain, ep.id as emp_proj_id , ep.employee_id, ep.project_id,ep.fte ,ep.start_date ,ep.end_date, ep.status , w.id as weekid , w.employee_project_id , w.week_num , w.prod_hours, w.month, w.year , w.manual_flag, w.network_id ,w.proj_description from employee e , project p , employee_project ep , week_utilization w where e.id = ep.employee_id and p.id = ep.project_id and ep.id = w.employee_project_id and w.month ='"+input_month+"' and w.year ='"+yr+"' ";
      } 
      else{
    	    Date today = Calendar.getInstance().getTime();
    	    DateFormat  fmt = new SimpleDateFormat("dd/MM/yyyy");
    	    DateFormat  format = new SimpleDateFormat("dd/MMM/yyyy");
    	    String  d= fmt.format(today);
    	    String cur_date = format.format(today);
    	    String dt [] =d.split("/");
    	    String dt_ar[]= cur_date.split("/");                                                 
    	    String curentMonth= dt_ar[1].toUpperCase();
    	    if("JAN".equals(curentMonth) ||"MAR".equals(curentMonth) || "MAY".equals(curentMonth) || "JUL".equals(curentMonth) || "AUG".equals(curentMonth)|| "OCT".equals(curentMonth) || "DEC".equals(curentMonth)){
    	    	end_day = "31";
    	    }else if("FEB".equals(curentMonth)){
    	    	end_day = "28";	
    	    }
    	    else{
    	    	end_day="30";
    	    }
    	    
    	    
    	    System.out.println("YEAR:"+dt[2]+"MON:"+dt[1]);
    	    yr = dt[2];
    	   input_month = dt[1].substring(1, 2);
    	  int current_month =Integer.valueOf(input_month)-1;
    	  week_of_month =  getWeekNumber(current_month,Integer.valueOf(yr)); 
    	   
    	  strat_dat ="01"+"-"+curentMonth+"-"+yr;
    	  end_dat= end_day+"-"+curentMonth+"-"+yr;
    	//  System.out.println("strat_dat:"+strat_dat);
    	//  System.out.println("end_dat:"+end_dat);
    	
    	  no_of_wkDays  =   NumberOfWorkingDays.getNoOfWorkingDays(strat_dat, end_dat);
    	//  System.out.println("no_of_wkDays:"+no_of_wkDays);
    	  System.out.println("current month and year:"+input_month +";"+yr);
         query = "select e.id as empid , e.signum_id as signum ,e.password as pwd  , e.emp_name  as Ename, e.manager_id as ManagerID , p.id as ids ,  p.pid ,  p.pname , p.region, p.customer , p.domain, ep.id as emp_proj_id , ep.employee_id, ep.project_id,ep.fte ,ep.start_date ,ep.end_date, ep.status , w.id as weekid , w.employee_project_id , w.week_num , w.prod_hours, w.month, w.year , w.manual_flag, w.network_id ,w.proj_description from employee e , project p , employee_project ep , week_utilization w where e.id = ep.employee_id and p.id = ep.project_id and ep.id = w.employee_project_id and w.month ='"+input_month+"' and w.year ='"+yr+"' ";
      }
      System.out.println("query is:"+query);
   
    List<Object[]> list = (List<Object[]>)entityManager.createNativeQuery(query).getResultList() ;
    List<ReportStructure> struct_list = new ArrayList<ReportStructure>();
    
       if(list!= null && list.size()>0){
    	   System.out.println("list size:"+list.size());
    	   for(int i = 0;i<list.size();i++){
    		 ReportStructure  struct = new ReportStructure();   
    		 String id = list.get(i)[0].toString();
    		 struct.setId(id);
    		 String signum  = list.get(i)[1].toString();
    		 struct.setSignum(signum);
    		 String password =list.get(i)[2].toString();
    		 struct.setPassword(password);
    		 String emp_name = list.get(i)[3].toString();
    		 struct.setEmp_name(emp_name);
    		// String manager_id = list.get(i)[4].toString();
    		// struct.setManager_id(manager_id);
    		 String emp_proj_id = list.get(i)[5].toString();
    		 struct.setEmp_proj_id(emp_proj_id);
    		 
    		 String id1 =  list.get(i)[6].toString();
    		 struct.setId1(id1);
    		 String p_name =  list.get(i)[7].toString();
    		 struct.setP_name(p_name);
    		 String region =  list.get(i)[8].toString();
    		 struct.setRegion(region);
    		 String customer =  list.get(i)[9].toString();
    		 struct.setCustomer(customer);
    		 String domain =  list.get(i)[10].toString();
    		 struct.setDomain(domain);
    		 String id_2 =  list.get(i)[11].toString();
    		 struct.setId_2(id_2);
    		 String employee_id =  list.get(i)[12].toString();
    		 struct.setEmployee_id(employee_id);
    		 String project_id =  list.get(i)[13].toString();
    		 struct.setProject_id(project_id);
    		 String fte =  list.get(i)[14].toString();
    		 struct.setFte(fte);
    		 String start_date =  list.get(i)[15].toString();
    		 struct.setStart_date(start_date);
    		 String end_date =  list.get(i)[16].toString();
    		 struct.setEnd_date(end_date);
    		 String status =  list.get(i)[17].toString();
    		 struct.setStatus(status);
    		 String id3 =  list.get(i)[18].toString();
    		 struct.setId3(id3);
    		 String employee_project_id =  list.get(i)[19].toString();
    		 struct.setEmployee_project_id(employee_project_id);
    		 String week_no =  list.get(i)[20].toString();
    		 struct.setWeek_no(week_no);
    		 String prod_hours =  list.get(i)[21].toString();
    		 struct.setProd_hours(prod_hours);
    		 String month =  list.get(i)[22].toString();
    		 struct.setMonth(month);
    		 String year =  list.get(i)[23].toString();
    		 struct.setYear(year);
    		 String manual_flag =  list.get(i)[24].toString();
    		 struct.setManual_flag(manual_flag);
    	      //  String network_id =  list.get(i)[25].toString();
    		 // struct.setNetwork_id(network_id);
    		// String project_description =  list.get(i)[26].toString();
    	   // struct.setProject_description(project_description);
    		  struct_list.add(struct);
    
    		   
    	   }
    	   
       }
       List<ReportDto> report_Dot =  papulateReportStructure(struct_list,no_of_wkDays,week_of_month);
           
        /* if(output_report!=null && output_report.size()>0){
        	 System.out.println("output_report:"+output_report.size());
        	 for(ReportDto rep:output_report){
        		 System.out.println("obj:"+rep.getEmpName()+":"+rep.getRegion()+":"+rep.getSignum()+":"+rep.getW1()+":"+rep.getW2()+":"+rep.getW3()+":"+rep.getW4()+":"+rep.getWeek1_flag()+":"+rep.getWeek2_flag()+":"+rep.getWeek3_flag()+":"+rep.getWeek4_flag());
        	 }
         }*/
      
       return report_Dot ;    
           
	}
	
/*	public Map<String,List<String>> papulateManualFalg(Map<String,List<ReportStructure>> report_maps){
		 
		Map<String,List<String>> manualEntryMap = new HashMap<String, List<String>>();
		if(manualFlagY_set!=null){
			for(String set :manualFlagY_set){
				String  signum = set.substring(0, 7);
				String week_no = set.substring(7, 8);
				System.out.println("Signum week:"+signum+":"+week_no);
				List<String> wk_list = manualEntryMap.get(signum);
				 if(wk_list!=null && wk_list.size()>0 ){
					 wk_list.add(week_no);
				 }
				 else{
					 List<String> week_list = new  ArrayList<String>(); 
					 week_list.add(week_no);
					 manualEntryMap.put(signum, week_list);
				 }
				
			}
		}
		
		return manualEntryMap ;
	}*/
	
	 public int getWeekNumber(int month,int year){
		    Calendar c = Calendar.getInstance();
	    	c.set(Calendar.DAY_OF_MONTH, 1);
	    	c.set(Calendar.MONTH,month );
	    	c.set(Calendar.YEAR, year);
	    	
	    	int week = c.get(Calendar.WEEK_OF_YEAR);
		 return week;
	 }
	 public static boolean isInteger(String s) {
		    try { 
		        Integer.parseInt(s); 
		    } catch(NumberFormatException e) { 
		        return false; 
		    } catch(NullPointerException e) {
		        return false;
		    }
		    // only got here if we didn't return false
		    return true;
		}
	
	
	@Transactional(propagation=Propagation.REQUIRES_NEW)
	@Override
	public void updateWeek(ReportDto[] input_data) {
		// TODO Auto-generated method stub
		try{
			String id1 ;
			String id2 ;
			String id3 ;
			String id4 ;
			String sql ="";
			String week_util_sql ="";
			WeekUtilization week_util = null;
			List<Object[]>  list =null;
			
			for(ReportDto input :input_data){
				
				id1 = input.getId1();
				id2 = input.getId2();
				id3 = input.getId3();
				id4 = input.getId4();
				
		
				if(id1!=null && !"".equals(id1)){
                 Long long_obj = new Long(id1); 
					
				long id =long_obj.longValue();
				 week_util = entityManager.find(WeekUtilization.class, id);
				 if(week_util!=null){
					String hr = input.getW1();
					String old_hr = week_util.getProdHours().toString();
					System.out.println("old_hour:"+old_hr+"new hour:"+hr);
					 if(!hr.equals(old_hr)){
					  BigDecimal big = new BigDecimal(hr);
					
					  week_util.setProdHours(big); 
					  week_util.setManualFlag("Y");
					  entityManager.merge(week_util);
					  entityManager.flush();
					 }
				 }
				}
				else if(input.getW1()!= null){/*
					System.out.println("input.getW1():"+input.getW1());
				//	WeekUtilization obj = new WeekUtilization();
					String empId = input.getEmpid();
					String hr = input.getW1();
					BigDecimal big = new BigDecimal(hr);
					BigDecimal week_no = new BigDecimal("1");
					
					sql ="select * from employee_project ep where ep.employee_id = '"+empId+"' ";
					List<Object[]>  lists = (List<Object[]>)entityManager.createNativeQuery(sql).getResultList();
					System.out.println("employee_projectlist:"+lists.size());
					 WeekUtilization obj = null;
					List<WeekUtilization> util_list = new ArrayList<WeekUtilization>();
					 EmployeeProject ep = new EmployeeProject();
					  if(lists!=null && lists.size()>0){
						  for(int i = 0 ; i<lists.size(); i++){
						   
							String id =  lists.get(i)[0].toString();
							week_util_sql = "select * from week_utilization w where w.employee_project_id = '"+id+"' ";
							
							List<Object[]>  util_lists = (List<Object[]>)entityManager.createNativeQuery(week_util_sql).getResultList();
							 System.out.println("week_utilization util_lists:"+util_lists.size());
							 if(util_lists!=null){
								 for(int j = 0 ; j<util_lists.size(); i++){
								     obj = new WeekUtilization();
									 String employee_proj_id =util_lists.get(j)[1].toString();
									 String month = util_lists.get(j)[4].toString();
									 String yr = util_lists.get(j)[5].toString();
									 obj.setManualFlag("Y");
									 obj.setWeekNum(week_no);
									 obj.setProdHours(big);
									 util_list.add(obj);
									 
								 }
								 
							 }
							 
						  }
						  ep.setWeekUtilizations(util_list); 
						  obj.setEmployeeProject(ep);
					  }
					
					  entityManager.persist(obj);
					  entityManager.flush();
				*/}
				if(id2!=null && !"".equals(id2)){
					Long long_obj = new Long(id2); 
					
					long id21 =long_obj.longValue();
					System.out.println("id in daoimpl:"+id2);
					WeekUtilization week = entityManager.find(WeekUtilization.class,id21 );
					System.out.println("week:"+week);
					 if(week!=null){
						String hrs = input.getW2();
						String old_hr =week.getProdHours().toString();
						if(!hrs.equals(old_hr)){
						
						BigDecimal big = new BigDecimal(hrs);
					
						week.setProdHours(big); 
						week.setManualFlag("Y");
						entityManager.merge(week);
						entityManager.flush();
						}  
					 }
				 } 
					 
					 if(id3!=null && "".equals(id3)){
							Long long_objs = new Long(id3); 
							
							long id_3 =long_objs.longValue();
							System.out.println("id in daoimpl:"+id_3 );
							WeekUtilization week_obj = entityManager.find(WeekUtilization.class,id_3  );
							System.out.println("week:"+week_obj);
							 if(week_obj!=null){
								String hr = input.getW3();
								String old_hr =week_obj.getProdHours().toString();
								
								if(!hr.equals(old_hr)){
								BigDecimal big = new BigDecimal(hr);
								
								week_obj.setProdHours(big); 
								week_obj.setManualFlag("Y");
								  entityManager.merge(week_obj);
								  entityManager.flush();
								}  
							 }
							
				       }
					 
					 if(id4!=null && !"".equals(id4)){
							Long long_objs = new Long(id4); 
							
							long id_4 =long_objs.longValue();
							System.out.println("id in daoimpl:"+id_4 );
							WeekUtilization week_obj = entityManager.find(WeekUtilization.class,id_4);
							System.out.println("week:"+week_obj);
							 if(week_obj!=null){
								String hr = input.getW4();
								String old_hr =week_obj.getProdHours().toString();
								if(!hr.equals(old_hr)){
								
							    BigDecimal big = new BigDecimal(hr);
								
								week_obj.setProdHours(big); 
								week_obj.setManualFlag("Y");
								  entityManager.merge(week_obj);
								  entityManager.flush();
								 } 
							 }
							
				       } 
				 
	          }
			
		}
		
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public List<ReportDto> papulateReportStructure(List<ReportStructure> report_list ,int no_of_workDays, int start_weekOftheMonth ){
		
		Map<String,List<ReportStructure>> report_map = new HashMap<String,List<ReportStructure>>();	
//		Map<String,Map<String, String>> map2  = new HashMap<String,Map<String, String>>();		
	    List<ReportDto> output_report = new ArrayList<ReportDto>();
	    
	    Map<String, List<String>> week_list_map = new HashMap<String, List<String>>();
		
	 if(report_list!= null && report_list.size()>0){
      	   System.out.println("struct_list:"+report_list.size());
      	for(ReportStructure report :report_list){
      		String signum = report.getSignum();
      		String id = report.getId3();
      		System.out.println("Utilization id:"+id);
      		List<ReportStructure>  lists = report_map.get(signum);
      		if(lists!=null && lists.size()>0){
      			lists.add(report);
      		}
      		else{
      			List<ReportStructure> struct_lists = new ArrayList<ReportStructure>();	
      			struct_lists.add(report);
      			report_map.put(signum, struct_lists);
      		   }
      	    }
           }
		 
		 Set<String> set = report_map.keySet();                      
         Map<String,String> prod_hr_map = new HashMap<String, String>();
         System.out.println("week_of_month:"+start_weekOftheMonth);
          for(String key :set){
          	List<String> week_list = new ArrayList<String>();
          	List<ReportStructure> ls = report_map.get(key);
          	 System.out.println(key);
          	 System.out.println("---------");
          	  for(ReportStructure rp :ls){
          		  System.out.println("week_NO"+rp.getWeek_no() +"prodHours:"+rp.getProd_hours());
          		  String map_key  = key+rp.getWeek_no();
          		  if("Y".equals(rp.getManual_flag())){
          			  week_list.add(rp.getWeek_no());
          			
          		  }
          		  prod_hr_map.put(map_key, rp.getProd_hours());
          		//  utilization_id_map.put(map_key, rp.getId3());
          	    }
          	
          	   week_list_map.put(key, week_list);
             }
          if(report_map!=null && report_map.size()>0){
        	  Set<String> rp_set = report_map.keySet();
        	  String signum_id ="";
        	  String wk_num ="";
        	  
        	  for(String str :rp_set){
        		  
        		  ReportDto report = new ReportDto(); 		
        		  List<ReportStructure> rp_str_list = report_map.get(str);
        		   { 
        			   double fte_value =0.0; 
        			  for(ReportStructure reportStructure:rp_str_list){
        			  Map<String,String> utilization_id_map = new HashMap<String, String>();  
        			   List<String> week_Lists = week_list_map.get(str);
        			   System.out.println("week_list_size:"+week_Lists);
        			   report.setSignum(str);
        			 //  report.setCustomer(rp_str_list.get(0).getCustomer());
        			   report.setDomain(reportStructure.getDomain());
        			   report.setEmpName(reportStructure.getEmp_name());
        			   report.setRegion(reportStructure.getRegion());
        			   report.setEmpid(reportStructure.getId());
        			   String fte = reportStructure.getFte();
        			   System.out.println("fte:"+fte);
        			   boolean is_integer=  isInteger(fte);
        			   
        			   System.out.println("is_integer_value:"+is_integer);
        			    if(!is_integer){
        			     fte_value= Double.parseDouble(fte);
        			   
        			      fte_value = no_of_workDays*fte_value;
        			      report.setICRRB(String.valueOf(fte_value));
        			    }
        			    else {
        			    int fte_int  = Integer.parseInt(fte);
        			    fte_int= fte_int*no_of_workDays;
        			    report.setICRRB(String.valueOf(fte_int));
        			    }
        			  //  System.out.println("fte*noof Working:"+fte);
        			   
        			   utilization_id_map.put(reportStructure.getWeek_no(), reportStructure.getId3());
        			   
        			 //  report.setId1(reportStructure.getId3());
        			   if(prod_hr_map!=null){
        				 Set<String>  set_keys = prod_hr_map.keySet(); 
        				  Set<String> util_map  =  utilization_id_map.keySet();
        				  for(String key :set_keys){
        					  signum_id = key.substring(0, 7);
        					String hour ="";
        					String wkid ="";
        					if(str.equals(signum_id)){
        						if(key.length()<=8){
        						wk_num = key.substring(7, 8);
        						}
        						else{
        						wk_num = key.substring(7, 9);	
        						}
        						
        						 for(String week_no:util_map){
        							 wkid =  utilization_id_map.get(week_no);
        							 int tempWeek = Integer.parseInt(week_no);
        							 System.out.println("tempWeek"+tempWeek);
        							 int diffs = tempWeek-start_weekOftheMonth+1;
        							 System.out.println("diff"+diffs);
        							 week_no=String.valueOf(diffs);
        							 if("1".equals(week_no)){
        								 report.setId1(wkid);	 
        							 }
        							 if("2".equals(week_no)){
        								 report.setId2(wkid);;	 
        							 }
        							 if("3".equals(week_no)){
        								 report.setId3(wkid);	 
        							 }
       							    if("4".equals(week_no)){
        								 report.setId4(wkid);	 
        							 }
       							    if("5".equals(week_no)){
    								 report.setId5(week_no);	 
    							    }
        							 
        						 }
            					hour = prod_hr_map.get(key);
            				 int tempWeeks = Integer.parseInt(wk_num);
   							 System.out.println("tempWeek"+tempWeeks);
   							 int diff = tempWeeks-start_weekOftheMonth+1;
   							 System.out.println("diff"+diff);
   							 wk_num =String.valueOf(diff);
            					if("1".equals(wk_num)){
            						if(week_Lists.contains(String.valueOf(tempWeeks))){
            							report.setWeek1_flag("Y");
            						}
            					report.setW1(hour);	
            					
            					
            					}
            					else if("2".equals(wk_num)){
            						
            						if(week_Lists.contains(String.valueOf(tempWeeks))){
            							report.setWeek2_flag("Y");
                					}
            					 report.setW2(hour);
            					 
            					}
            					else if("3".equals(wk_num)){
            						if(week_Lists.contains(String.valueOf(tempWeeks))){
            							report.setWeek3_flag("Y");
                					}
            						report.setW3(hour);
            					}
            					else if("4".equals(wk_num)){
            						if(week_Lists.contains(String.valueOf(tempWeeks))){
            							report.setWeek4_flag("Y");
                					}
            						report.setW4(hour);
            					}
            					else if("5".equals(wk_num)){
            						if(week_Lists.contains(String.valueOf(tempWeeks))){
            							report.setWeek4_flag("Y");
                					}
            						report.setW5(hour);
            					}
        					}
        				  }
        			   }
        		  
        			}  
        			   
        		   
        		   }
        		   
        		   output_report.add(report);
        	  }
           }
          
          
		return output_report;
	}

}
